package fr.lelouet.monitoring.perf


import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class Tools {
	
	private static final Logger logger = LoggerFactory.getLogger(Tools.class)
	
	/** convert a String from the perf tool to a map of key->value*/
	public static Map<String, String> convertString(String data) {
		Map map = [:]
		data.split("\n").each {
			if(it.length()>0) {
				String[] formatted = it.replaceAll("\\s+", " ").replaceAll("^ ", "").replaceAll(" \$", "").split(" ")
				if(formatted[0].startsWith("Perf")) {
					map["pid"]=formatted[6][1..formatted[6].length()-3]
				} else {
					if( ! formatted[0].startsWith("<")) {
						map[formatted[1]]= formatted[0].replace (',', '.')
					}
				}
			}
		}
		return map
	}
	
	public static final String BENCH_DURATION_KEY= "seconds"
	
	/** convert a map of values over a given time, mapped as "seconds", to average values.<br />
	 * every data but the "seconds" and "pid" mapped ones is divided by "seconds"<br />
	 * @return a map of numeric data divided by the duration, if available */
	public static Map<String, String> toTimeProportionnal(Map map) {
		if(! map.containsKey(BENCH_DURATION_KEY)) {
			return null
		}
		float seconds = Float.parseFloat (map[BENCH_DURATION_KEY])
		if(seconds<=0) return [:]
		Map<String, String> ret = new HashMap<String, String>();
		map.each{ key, value -> 
			if(goodEvent(key)) {
				try{
					ret[key]=(Float.parseFloat(value) / seconds).toString()
				} catch(NumberFormatException nfe) {
					logger.error(nfe.toString())
				}
			} else {
				//System.out.println("bad event "+key+" ; good events are "+findAllowedEvents());
				if(key!=BENCH_DURATION_KEY) { ret[key]=value
				}
				else { ret[key]="1"
				}
			}
		}
		return ret
	}
	
	/** the key the time value is stored with*/
	public static final String TIME_KEY="time"
	
	public static void timeMap(Map map) {
		map[TIME_KEY]=System.currentTimeMillis().toString()
	}
	
	
	
	static Set<String> allowedEvents=null
	
	/** @return is the given event name valid for the linux perf tool ?*/
	public static boolean goodEvent(String event) {
		return getAllowedEvents().contains(event)
	}
	
	public static final List<String> allowedEventsString = [
		"cycles",
		"instructions",
		"cache-references",
		"cache-misses",
		"branches",
		"branch-misses",
		"bus-cycles",
		"cpu-clock",
		"task-clock",
		"page-faults",
		"faults",
		"minor-faults",
		"major-faults",
		"context-switches",
		"cs",
		"cpu-migrations",
		"migrations",
		"alignment-faults",
		"emulation-faults"
	]
	
	/** @return a set of the allowed events*/
	public static Set<String> getAllowedEvents(){
		if(allowedEvents==null) {
			allowedEvents= new HashSet<String>(allowedEventsString)
		}
		return allowedEvents
	}
	
	public static Set<String> getSimpleEvents() {
		return new HashSet<String>(allowedEventsString.subList(0, 7))
	}
	
	public static final String HVIdKEY="HVId"
	public static void markHypervisor(Map map, String HVId) {
		map[HVIdKEY]=HVId;
	}
}
